package cn.chiship.framework.upms.biz.base.service.impl;

import cn.chiship.framework.common.config.properties.GlobalProperties;
import cn.chiship.framework.common.constants.CommonCacheConstants;
import cn.chiship.framework.common.constants.CommonConstants;
import cn.chiship.framework.common.pojo.vo.EmailSettingVo;
import cn.chiship.framework.common.pojo.vo.SystemConfigVo;
import cn.chiship.framework.common.quartz.CronTaskRegistrar;
import cn.chiship.framework.common.quartz.SchedulingRunnable;
import cn.chiship.framework.common.util.FrameworkUtil2;
import cn.chiship.framework.upms.biz.base.service.CacheService;
import cn.chiship.framework.upms.biz.system.entity.*;
import cn.chiship.framework.upms.biz.system.service.*;
import cn.chiship.framework.upms.biz.user.entity.UpmsPost;
import cn.chiship.framework.upms.biz.user.entity.UpmsPostExample;
import cn.chiship.framework.upms.biz.user.service.UpmsPostService;
import cn.chiship.sdk.cache.service.RedisService;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.base.constants.CacheConstants;
import cn.chiship.sdk.framework.pojo.vo.RegionVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author lijian
 */
@Service
public class CacheServiceImpl implements CacheService {
    private static final Logger LOGGER = LoggerFactory.getLogger(CacheServiceImpl.class);

    @Resource
    RedisService redisService;

    @Resource
    GlobalProperties globalProperties;

    @Resource
    CacheAsyncService cacheAsyncService;

    @Resource
    UpmsProofService upmsProofService;

    @Resource
    UpmsRegionService upmsRegionService;

    @Resource
    UpmsEmailSettingService upmsEmailSettingService;

    @Resource
    UpmsConfigService upmsConfigService;

    @Resource
    UpmsSystemService upmsSystemService;

    @Resource
    UpmsDataDictService upmsDataDictService;

    @Resource
    UpmsPostService upmsPostService;

    @Resource
    UpmsQuartzJobService upmsQuartzJobService;

    @Resource
    UpmsAppVersionService upmsAppVersionService;

    @Override
    public void cacheConfigs() {
        String key = CommonCacheConstants.buildKey(CacheConstants.REDIS_SYSTEM_CONFIG_PREFIX);
        redisService.del(key);
        UpmsConfigExample upmsConfigExample = new UpmsConfigExample();
        upmsConfigExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO);
        List<UpmsConfig> upmsConfigs = upmsConfigService.selectByExample(upmsConfigExample);
        upmsConfigs.forEach(upmsConfig -> {
            SystemConfigVo systemConfigVo = new SystemConfigVo();
            BeanUtils.copyProperties(upmsConfig, systemConfigVo);
            redisService.hset(key, systemConfigVo.getParamCode(), systemConfigVo);
        });

    }

    /**
     * 缓存系统数据
     */
    @Override
    public void cacheSystems() {
        String key = CommonCacheConstants.buildKey(CacheConstants.REDIS_SYSTEM_PREFIX);
        redisService.del(key);
        UpmsSystemExample upmsSystemExample = new UpmsSystemExample();
        upmsSystemExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO).andIsDisabledEqualTo(BaseConstants.NO);
        upmsSystemExample.setOrderByClause(" orders desc ");
        List<UpmsSystem> upmsSystems = upmsSystemService.selectByExample(upmsSystemExample);
        for (UpmsSystem upmsSystem : upmsSystems) {
            redisService.hset(key, upmsSystem.getCode(), upmsSystem);
        }
    }

    @Override
    public void cacheProofs() {
        UpmsProofExample upmsProofExample = new UpmsProofExample();
        upmsProofExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO).andIsSelfEqualTo(BaseConstants.YES);
        if (upmsProofService.countByExample(upmsProofExample) == 0) {
            UpmsProof upmsProof = new UpmsProof();
            upmsProof.setIsSelf(BaseConstants.YES);
            upmsProof.setProjectName(CommonConstants.COMMON_PROJECT_NAME_DESC);
            upmsProof.setProjectDesc(CommonConstants.COMMON_PROJECT_NAME_DESC);
            upmsProof.setIsDisabled(BaseConstants.NO);
            upmsProofService.insertSelective(upmsProof);
            LOGGER.info("已生成新秘钥");
        }
        String key = CommonCacheConstants.buildKey(CacheConstants.REDIS_PROOF_PREFIX);
        redisService.del(key);

        List<UpmsProof> proofs = new ArrayList<>();
        UpmsProof upmsProof = new UpmsProof();
        upmsProof.setIsSelf(BaseConstants.YES);
        upmsProof.setProjectName(CommonConstants.COMMON_PROJECT_NAME_DESC);
        upmsProof.setProjectDesc(CommonConstants.COMMON_PROJECT_NAME_DESC);
        upmsProof.setIsDisabled(BaseConstants.NO);
        upmsProof.setAppId(globalProperties.getAppId());
        upmsProof.setAppKey(globalProperties.getAppKey());
        upmsProof.setAppSecret(globalProperties.getAppSecret());
        upmsProof.setSignKey(globalProperties.getSignKey());
        upmsProof.setPrivateKey(globalProperties.getPrivateKey());
        upmsProof.setPublicKey(globalProperties.getPublicKey());
        proofs.add(upmsProof);

        upmsProofExample = new UpmsProofExample();
        upmsProofExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO).andIsDisabledEqualTo(BaseConstants.NO);
        proofs.addAll(upmsProofService.selectByExample(upmsProofExample));
        proofs.forEach(proof -> {
            JSONObject json = (JSONObject) JSON.toJSON(proof);
            json.put("projectId", FrameworkUtil2.getGlobalProperties().getId());
            redisService.hset(key, proof.getAppId(), json);
        });

    }

    @Override
    public void cacheDataDict() {
        UpmsDataDictExample upmsDataDictExample = new UpmsDataDictExample();
        upmsDataDictExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO).andPidIsNotNull();
        List<UpmsDataDict> upmsDataDicts = upmsDataDictService.selectByExample(upmsDataDictExample);

        String dataDictItemKey = CommonCacheConstants.buildKey(CacheConstants.REDIS_DATA_DICT_ITEM_PREFIX);
        redisService.del(dataDictItemKey);
        Map<String, String> dataDictCodeMap = Maps.newHashMapWithExpectedSize(7);
        Map<String, List<UpmsDataDict>> mapData = Maps.newHashMapWithExpectedSize(7);
        for (UpmsDataDict upmsDataDict : upmsDataDicts) {
            if ("0".equals(upmsDataDict.getPid())) {
                dataDictCodeMap.put(upmsDataDict.getId(), upmsDataDict.getDataDictCode());
                mapData.put(upmsDataDict.getDataDictCode(), new ArrayList<>());
            }
        }
        for (Map.Entry<String, String> entry : dataDictCodeMap.entrySet()) {
            String pid = entry.getKey();
            String code = entry.getValue();
            List<UpmsDataDict> upmsDataDictItemList = mapData.get(code);
            for (UpmsDataDict upmsDataDict : upmsDataDicts) {
                if (upmsDataDict.getPid().equals(pid)) {
                    upmsDataDictItemList.add(upmsDataDict);
                }
            }
            mapData.put(code, upmsDataDictItemList);
            redisService.hset(dataDictItemKey, code, mapData.get(code));
        }
    }

    @Override
    public void cacheRegions() {
        String key = CommonCacheConstants.buildKey(CacheConstants.REDIS_REGIONS_PREFIX);
        redisService.removeAll(key);
        UpmsRegionExample regionExample = new UpmsRegionExample();
        regionExample.createCriteria().andPidEqualTo(CommonConstants.PROVINCE_PID);
        /**
         * 省
         */
        List<UpmsRegion> provinces = upmsRegionService.selectByExample(regionExample);


        List<RegionVo> provinceVos = new ArrayList<>();
        for (UpmsRegion province : provinces) {
            RegionVo regionVo = new RegionVo();
            BeanUtils.copyProperties(province, regionVo);
            provinceVos.add(regionVo);
        }

        redisService.hset(key, String.valueOf(CommonConstants.PROVINCE_PID), provinceVos);

        regionExample = new UpmsRegionExample();
        regionExample.createCriteria().andPidNotEqualTo(CommonConstants.PROVINCE_PID);
        List<UpmsRegion> regions = upmsRegionService.selectByExample(regionExample);

        for (UpmsRegion province : provinces) {
            cacheAsyncService.cacheRegionsCity(province.getId(), regions);
        }
    }


    @Override
    public void cacheEmailSettingConfig() {
        String key = CommonCacheConstants.buildKey(CacheConstants.REDIS_EMAIL_SETTING_PREFIX);
        redisService.del(key);
        UpmsEmailSettingExample upmsEmailSettingExample = new UpmsEmailSettingExample();
        UpmsEmailSettingExample.Criteria criteria = upmsEmailSettingExample.createCriteria();
        criteria.andIsDeletedEqualTo(BaseConstants.NO);
        List<UpmsEmailSetting> upmsEmailSettings = upmsEmailSettingService.selectByExample(upmsEmailSettingExample);
        upmsEmailSettings.forEach(upmsEmailSetting -> {
            EmailSettingVo emailSettingVo = new EmailSettingVo();
            BeanUtils.copyProperties(upmsEmailSetting, emailSettingVo);
            redisService.hset(key, emailSettingVo.getType() + ";" + emailSettingVo.getOutreachInfoId(), emailSettingVo);
        });

    }

    @Override
    public void cachePosts() {
        String key = CommonCacheConstants.buildKey(CacheConstants.REDIS_POST_PREFIX);
        redisService.del(key);
        UpmsPostExample upmsPostExample = new UpmsPostExample();
        upmsPostExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO).andStatusEqualTo(Byte.valueOf("0"));
        List<UpmsPost> upmsPosts = upmsPostService.selectByExample(upmsPostExample);
        redisService.set(key, JSON.parseArray(JSON.toJSONString(upmsPosts)));
    }


    @Resource
    private CronTaskRegistrar cronTaskRegistrar;

    @Override
    public void initQuartzJob() {
        UpmsQuartzJobExample upmsQuartzJobExample = new UpmsQuartzJobExample();
        upmsQuartzJobExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO);
        List<UpmsQuartzJob> upmsQuartzJobs = upmsQuartzJobService.selectByExample(upmsQuartzJobExample);
        upmsQuartzJobs.forEach(quartzJob -> {
            if (BaseConstants.NO == quartzJob.getStatus()) {
                SchedulingRunnable task = new SchedulingRunnable(quartzJob.getJobClass(), quartzJob.getJobMethod(), quartzJob.getJobParam());
                cronTaskRegistrar.addCronTask(task, quartzJob.getJobCron());
            }
        });
    }


    @Override
    public void cacheApp() {
        List<UpmsAppVersion> appVersions = upmsAppVersionService.listNewsApp();
        String key = CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_APP_VERSION_PREFIX);
        redisService.del(key);
        appVersions.forEach(appVersion -> {
            redisService.hset(key, appVersion.getAppCode(), JSONObject.parseObject(JSONObject.toJSONString(appVersion)));
        });
    }
}
